package com.sitc.administrator.application.mqtt;

import android.os.Handler;
import android.util.Log;

import com.sitc.administrator.application.domain.event.MessageArrivedEvent;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.greenrobot.eventbus.EventBus;


import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class MqttManager {

    public static final String TAG = MqttManager.class.getSimpleName();

    private String host;
    private String username;
    private String password;
    private String clientId;
    private String topic;
    private MqttClient client;
    private MqttConnectOptions connectOptions;

    private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public  MqttManager(String host, String username, String password,String topic) {
        this.host = host;
        this.password = password;
        this.username = username;
        this.topic = topic;
        this.clientId = MqttClient.generateClientId();
    }


    public void start() {

        try {

            client = new MqttClient(host, clientId, new MemoryPersistence());
            connectOptions = new MqttConnectOptions();
            connectOptions.setUserName(username);
            connectOptions.setPassword(password.toCharArray());
            client.setCallback(mqttCallback);
            client.connect(connectOptions);
            subscribe(topic,1);


        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    public void subscribe(String topic, int qos) {
        if (client != null) {
            int[] Qos = {qos};
            String[] topic1 = {topic};
            try {
                client.subscribe(topic1, Qos);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    public void publish(String topic, String msg, boolean isRetained, int qos) {
        try {
            if (client != null) {
                MqttMessage message = new MqttMessage();
                message.setQos(qos);
                message.setRetained(isRetained);
                message.setPayload(msg.getBytes());
                client.publish(topic, message);
                Log.i(TAG, "publish:"+msg);
            }
        } catch (MqttPersistenceException e) {
            e.printStackTrace();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }


    private MqttCallback mqttCallback = new MqttCallback() {
        @Override
        public void connectionLost(Throwable cause) {
            Log.i(TAG,"connection lost");

            if(client !=null){
                try {
                    client.close();
                    client = null;
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }


        }

        @Override
        public void messageArrived(String topic, MqttMessage message) {

            String payload = new String(message.getPayload());
            MessageArrivedEvent event =new MessageArrivedEvent(topic,payload);
            EventBus.getDefault().post(event);

        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
            Log.i(TAG,"deliveryComplete");
        }
    };


    public void checkNet(){

        scheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {

                if(client!=null && client.isConnected()){
                    return;
                }else{
                    start();
                }
            }
        }, 0, 60000, TimeUnit.MILLISECONDS);

    }






}